<?php
/**
*
* @package MoltX QuickChat Functions
* @author $Author: moltendorf $
* @version $Id: molten_chat_functions.php 157 2009-09-25 07:22:45Z moltendorf $
* @latest $URL: https://molten-chat.googlecode.com/svn/trunk/source/includes/molten_chat/molten_chat_functions.php $
* @copyright (c) 2005-2009 Matthew Oltendorf
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/

// PHP: Hypertext Preprocessor Document

/*
	Unfinished Items:
		1.
		2.
		3.
		4.
		5.
*/

/*
	Known Issues:
		1.
		2.
		3.
		4.
		5.
*/

/**
* @ignore
*/
if (
	!defined ('molten_chat')
)
	{
		die ('Unauthorised Access.');
	}

// Style: Object Oriented.

/* --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- //
// Name: molten_chat_functions_core
// Type: Singleton.
// Title: MoltX Chat Function Core Object.
// Description: Used by molten_chat_server to pass private variables.
// --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- */
class molten_chat_functions_core
	{
		protected static
			$_initialized,
			$comments,
			$directory,
			$extension,
			$formatting,
			$language,
			$room;

		/* --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- //
		// Name: __construct
		// Title: Class construction.
		// Variables: None.
		// Description: Disabled.
		// --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- */
		private function __construct ()
			{
				// No further actions required.
				return false;
			}

		/* --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- //
		// Name: __destruct
		// Title: Class destruction.
		// Variables: None.
		// Description: Disabled.
		// --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- */
		private function __destruct ()
			{
				// No further actions required.
				return false;
			}

		/* --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- //
		// Name: initialize
		// Title: Prepare object.
		// Variables: $variables
		//		1.	$variables: The array of references to molten_chat_server's internal variables.
		// Description: Load this object with required information.
		// --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- */
		public static function initialize (&$variables, $null = null)
			{
				if (
					!self :: $_initialized and
					is_array ($variables)
				)
					{
						foreach ($variables as $variable => &$value)
							{
								if (
									!property_exists (__CLASS__, $variable)
								)
									{
										continue;
									}

								// Assign data to self.
								self :: $$variable = &$value;
							}
						unset ($value);

						self :: $_initialized = true;

						return true;
					}

				return false;
			}
	}

/* --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- //
// Name: molten_chat_functions
// Type: Singleton.
// Title: MoltX Chat Function Object.
// Description: All of these functions can be called by users in chat rooms that have permission to do so.
// --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- */
final class molten_chat_functions extends molten_chat_functions_core
	{
		/* --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- //
		// Name: __construct
		// Title: Class construction.
		// Variables: None.
		// Description: Disabled.
		// --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- */
		private function __construct ()
			{
				// No further actions required.
				return false;
			}
		
		/* --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- //
		// Name: __destruct
		// Title: Class destruction.
		// Variables: None.
		// Description: Disabled.
		// --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- */
		private function __destruct ()
			{
				// No further actions required.
				return false;
			}

		/* --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- //
		// Name: initialize
		// Title: Cover-up.
		// Variables: $user, $arguments
		//	1.	$user: The user that called this function. Not used in this function.
		//	2.	$arguments: The array of arguments this function accepts.
		// Description: Does not do anything, simply prevents direct access to the parent object's function, can be changed to an actual slash command though.
		// --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- */
		public static function initialize (&$variables, $null = null)
			{
				return false;
			}

		/* --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- //
		// Name: announce
		// Title: Generate an announcement message.
		// Variables: $user, $arguments
		//	1.	$user: The user that called this function. Not used in this function.
		//	2.	$arguments: The array of arguments this function accepts.
		// Description: Send a announcement message. Also an example function for future additions.
		// --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- */
		public static function announce ($user, $arguments)
			{
				// Not used at the moment.
				static $format = array (
					array ('message')
				);

				// Bad, we should not rely on the phpBB 3 permissions system.
				try
					{
						global $user;

						if (
							$user -> data ['user_type'] != USER_FOUNDER
						)
							{
								return false;
							}
					}
				catch (Exception $exception)
					{
						// Swallow error (for use in standalone module).
					}

				// All arguments are sent in a single array, so we must manually check for their existence.
				if (
					empty ($arguments ['delete'])
				)
					{
						try
							{
								// We accept null here, so this is the best way to check for a variable that is set to null: try-catch blocks.

								/*
								 * Variables in the arguments array can be passed as any of the following types:
								 * 1. Boolean
								 * 2. Float
								 * 3. Integer
								 * 4. Null
								 * 5. String
								 *
								 * Variables can also be an array containing any of those five types.
								 */

								// This function supports "structured syntax."
								try
									{
										// This is our magic "test if it's set."
										try
											{
												$message = $arguments [1];

												$link = array (
													'local' => false,
													'uri' => $arguments [0]
												);
											}
										catch (Exception $exception)
											{
												$message = $arguments [0];

												$link = false;
											}
									}
								catch (Exception $exception)
									{
										// Optional parameters.
										try
											{
												// Either uri, or url must be set.
												try
													{
														// This is our magic "test if it's set."
														$uri = $arguments ['url'];
													}
												catch (Exception $exception)
													{
														// This is our magic "test if it's set."
														$uri = $arguments ['uri'];
													}

												$link = array (
													'local' => !empty ($arguments ['local']),
													'uri' => $uri
												);
											}
										catch (Exception $exception)
											{
												$link = false;
											}

										// Works just like /link, substituting the uri for the message if the message is not set.
										try
											{
												// This is our magic "test if it's set."
												$message = $arguments ['message'];
											}
										catch (Exception $exception)
											{
												// Substitute the link for the message.
												$message = $link ['uri'];
											}
									}
							}
						catch (Exception $exception)
							{
								// The message variable does not exist. Return false to make the message they sent display.
								return false;
							}

						// Check for a protocol.
						molten_chat_common :: standardize_link ($link);

						// Update the announcement variable in the chat server.
						parent :: $room ['data'] ['announcement'] = array (
							'message' => molten_chat_server :: to_string ($message),
							'link' => $link
						);
					}
				else
					{
						// Update the announcement variable in the chat server.
						parent :: $room ['data'] ['announcement'] = false;
					}

				// Check if we got any feedback.
				if (
					parent :: $room ['data'] ['announcement'] ['message'] === ''
				)
					{
						// No message.
						return false;
					}

				$file = parent :: $room ['files'] ['data'];

				$export = var_export (parent :: $room ['data'], true);

				$export = sprintf (parent :: $formatting ['data'], $export);

				// Open and/or create file.
				$pointer = fopen ($file, 'a+');

				// Acquire lock without blocking.
				while (!flock ($pointer, LOCK_EX | LOCK_NB))
					{
						// Generate a random number.
						$random = mt_rand (0, 250);

						// Sleep for 0.000 to 0.250 seconds. seconds.
						usleep (1000 * $random);
					}

				ftruncate ($pointer, 0);

				// Write data contents to new room descriptor.
				fwrite ($pointer, $export);
				
				// Close the file.
				flock ($pointer, LOCK_UN);
				fclose ($pointer);

				// Send a message to the system.
				/*
				 * The first parameter is the message itself.
				 * The second parameter is the user, we set this to null to make it a system message.
				 * The third parameter is whether or not the message is raw input from the outside world.
				 *		We set it to false because even though this is input, it was already cleaned.
				 * The fourth parameter is whether or not to call a slash command if the message begins with a slash.
				 *		You definitely should set this to false because if you don't, infinite loops can occur!
				 * The fifth parameter is whether or not this message is linked.
				 *
				 * Remember: The send function uses the internal function to_string;
				 *		to_string casts booleans, null values, and objects to their textual representation.
				 */
				if (
					parent :: $room ['data'] ['announcement'] !== false
				)
					{
						molten_chat_server :: send (molten_chat_server :: $language ['new_announcement'] . ': ' . molten_chat_server :: to_string ($message), null, false, false, $link);
					}
				else
					{
						molten_chat_server :: send (molten_chat_server :: $language ['no_announcement'], null, false, false);
					}

				// True means that the message the user sent is not displayed. False means it is displayed.
				return true;
			}

		/* --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- //
		// Name: site
		// Title: Alias.
		// Variables: $user, $arguments
		//	1.	$user: The user that called this function. Not used in this function.
		//	2.	$arguments: The array of arguments this function accepts.
		// Description: Alias of link.
		// --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- */
		public static function site ($user, $arguments) {return self :: link ($user, $arguments);}

		/* --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- //
		// Name: link
		// Title: Link a message.
		// Variables: $user, $arguments
		//	1.	$user: The user that called this function. Not used in this function.
		//	2.	$arguments: The array of arguments this function accepts.
		// Description: Make an entire message linked to a specific page. Also an example function for future additions.
		// --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- */
		public static function link ($user, $arguments)
			{
				// Not used at the moment.
				static $format = array (
					array ('uri'),
					array ('message')
				);

				if (
					$user !== false
				)
					{
						// Bad, we should not rely on the phpBB 3 permissions system.
						try
							{
								// Fix.
								$local_user = $user;

								global $user;

								if (
									$user -> data ['user_type'] != USER_FOUNDER
								)
									{
										// Force local to be false.
										$arguments ['local'] = false;
									}

								// Fix.
								unset($user);
								$user = $local_user;
							}
						catch (Exception $exception)
							{
								// Swallow error (for use in standalone module).
							}
					}
				else
					{
						$user = null;
					}

				// Convert to boolean without throwing an exception.
				$local = !empty ($arguments ['local']);

				$link = array (
					'local' => $local,
					'uri' => ''
				);

				// All future variables must exist, otherwise we just silently fail.
				try
					{
						// We accept null here, so this is the best way to check for a variable that is set to null: try-catch blocks.

						/*
						 * Variables in the arguments array can be passed as any of the following types:
						 * 1. Boolean
						 * 2. Float
						 * 3. Integer
						 * 4. Null
						 * 5. String
						 *
						 * Variables can also be an array containing any of those five types.
						 */

						// This function supports "structured syntax."
						 try
							{
								// This is our magic "test if it's set."
								$link ['uri'] = $arguments [0];

								// If message does not exist, we simply use the uri.
								$message = isset ($arguments [1]) ?
									$arguments [1] :
									$link ['uri'];
							}
						catch (Exception $exception)
							{
								// Either uri, or url must be set.
								try
									{
										// This is our magic "test if it's set."
										$link ['uri'] = $arguments ['url'];
									}
								catch (Exception $exception)
									{
										// This is our magic "test if it's set."
										$link ['uri'] = $arguments ['uri'];
									}

								// If message does not exist, we simply use the uri.
								$message = isset ($arguments ['message']) ?
									$arguments ['message'] :
									$link ['uri'];
							}

						// Check for a protocol.
						molten_chat_common :: standardize_link ($link);

						// Send a message to the system.
						/*
						 * The first parameter is the message itself.
						 * The second parameter is the user, we set this to null to make it a system message.
						 * The third parameter is whether or not the message is raw input from the outside world.
						 *		We set it to false because even though this is input, it was already cleaned.
						 * The fourth parameter is whether or not to call a slash command if the message begins with a slash.
						 *		You definitely should set this to false because if you don't, infinite loops can occur!
						 * The fifth parameter is whether or not this message is linked.
						 *
						 * Remember: The send function uses the internal function to_string;
						 *		to_string casts booleans, null values, and objects to their textual representation.
						 */
						// True means that the message the user sent is not displayed. False means it is displayed.
						return molten_chat_server :: send ($message, $user, false, false, $link);
					}
				catch (Exception $exception)
					{
						// Swallow error, we just return false at the end.
					}

				// True means that the message the user sent is not displayed. False means it is displayed.
				return false;
			}

		/* --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- //
		// Name: e, em, i, me
		// Title: Alias.
		// Variables: $user, $arguments
		//	1.	$user: The user that called this function. Not used in this function.
		//	2.	$arguments: The array of arguments this function accepts.
		// Description: Aliases of emote.
		// --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- */
		public static function e ($user, $arguments) {return self :: emote ($user, $arguments);}
		public static function em ($user, $arguments) {return self :: emote ($user, $arguments);}
		public static function i ($user, $arguments) {return self :: emote ($user, $arguments);}
		public static function me ($user, $arguments) {return self :: emote ($user, $arguments);}

		/* --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- //
		// Name: emote
		// Title: Emote.
		// Variables: $user, $arguments
		//	1.	$user: The user that called this function. Not used in this function.
		//	2.	$arguments: The array of arguments this function accepts.
		// Description: Sends a system message with the username appended.
		// --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- */
		public static function emote ($user, $arguments)
			{
				// Not used at the moment.
				static $format = array (
					'message' => true
				);

				// All arguments are sent in a single array, so we must manually check for their existence.
				try
					{
						// We accept null here, so this is the best way to check for a variable that is set to null: try-catch blocks.

						/*
						 * Variables in the arguments array can be passed as any of the following types:
						 * 1. Boolean
						 * 2. Float
						 * 3. Integer
						 * 4. Null
						 * 5. String
						 *
						 * Variables can also be an array containing any of those five types.
						 */

						// This function supports "structured syntax."
						try
							{
								// This is our magic "test if it's set."
								$message = $arguments [0];
							}
						catch (Exception $exception)
							{
								// This is our magic "test if it's set."
								$message = $arguments ['message'];
							}

						// Convert message to string.
						$message = molten_chat_server :: to_string ($message);
					}
				catch (Exception $exception)
					{
						// The message variable does not exist. Return false to make the message they sent display.
						return false;
					}

				if (
					$message == ''
				)
					{
						return false;
					}

				// Send a message to the system.
				/*
				 * The first parameter is the message itself.
				 * The second parameter is the user, we set this to null to make it a system message.
				 * The third parameter is whether or not the message is raw input from the outside world.
				 *		We set it to false because even though this is input, it was already cleaned.
				 * The fourth parameter is whether or not to call a slash command if the message begins with a slash.
				 *		You definitely should set this to false because if you don't, infinite loops can occur!
				 * The fifth parameter is whether or not this message is linked.
				 *		We have left it empty because it is false by default.
				 *
				 * Remember: The send function uses the internal function to_string;
				 *		to_string casts booleans, null values, and objects to their textual representation.
				 */
				// True means that the message the user sent is not displayed. False means it is displayed.
				return molten_chat_server :: send ($user . ' ' . $message, null, false, false);
			}
		
		/* --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- //
		// Name: system
		// Title: Send system message.
		// Variables: $user, $arguments
		//	1.	$user: The user that called this function. Not used in this function.
		//	2.	$arguments: The array of arguments this function accepts.
		// Description: Send a system message. Also an example function for future additions.
		// --|-- ----- ----- ----- -----|----- ----- ----- ----- --|-- */
		public static function system ($user, $arguments)
			{
				// Not used at the moment.
				static $format = array (
					'message' => true
				);
				
				// Bad, we should not rely on the phpBB 3 permissions system.
				try
					{
						global $user;

						if (
							$user -> data ['user_type'] != USER_FOUNDER
						)
							{
								return false;
							}
					}
				catch (Exception $exception)
					{
						// Swallow error (for use in standalone module).
					}

				// All arguments are sent in a single array, so we must manually check for their existence.
				try
					{
						// We accept null here, so this is the best way to check for a variable that is set to null: try-catch blocks.

						/*
						 * Variables in the arguments array can be passed as any of the following types:
						 * 1. Boolean
						 * 2. Float
						 * 3. Integer
						 * 4. Null
						 * 5. String
						 *
						 * Variables can also be an array containing any of those five types.
						 */

						// This function supports "structured syntax."
						try
							{
								// This is our magic "test if it's set."
								try
									{
										$message = $arguments [1];

										$link = array (
											'local' => false,
											'uri' => $arguments [0]
										);
									}
								catch (Exception $exception)
									{
										$message = $arguments [0];

										$link = false;
									}
							}
						catch (Exception $exception)
							{
								// Optional parameters.
								try
									{
										// Either uri, or url must be set.
										try
											{
												// This is our magic "test if it's set."
												$uri = $arguments ['url'];
											}
										catch (Exception $exception)
											{
												// This is our magic "test if it's set."
												$uri = $arguments ['uri'];
											}

										$link = array (
											'local' => !empty ($arguments ['local']),
											'uri' => $uri
										);
									}
								catch (Exception $exception)
									{
										$link = false;
									}

								// Works just like /link, substituting the uri for the message if the message is not set.
								try
									{
										// This is our magic "test if it's set."
										$message = $arguments ['message'];
									}
								catch (Exception $exception)
									{
										// Substitute the link for the message.
										$message = $link ['uri'];
									}
							}
					}
				catch (Exception $exception)
					{
						// The message variable does not exist. Return false to make the message they sent display.
						return false;
					}

				if (
					$message == ''
				)
					{
						return false;
					}

				// Check for a protocol.
				molten_chat_common :: standardize_link ($link);

				// Send a message to the system.
				/*
				 * The first parameter is the message itself.
				 * The second parameter is the user, we set this to null to make it a system message.
				 * The third parameter is whether or not the message is raw input from the outside world.
				 *		We set it to false because even though this is input, it was already cleaned.
				 * The fourth parameter is whether or not to call a slash command if the message begins with a slash.
				 *		You definitely should set this to false because if you don't, infinite loops can occur!
				 * The fifth parameter is whether or not this message is linked.
				 *
				 * Remember: The send function uses the internal function to_string;
				 *		to_string casts booleans, null values, and objects to their textual representation.
				 */
				// True means that the message the user sent is not displayed. False means it is displayed.
				return molten_chat_server :: send ($message, null, false, false, $link);
			}
	}